/**
 * Copyright 2009 Sergio Bossa
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.googlecode.actorom;

import com.googlecode.actorom.support.ActorExecutionException;

/**
 * A <code>FutureResult</code> represents the asynchronous result of a message computation made by an actor.<br>
 * It provides methods for waiting for the message computation to complete, checking the computation status and
 * retrieving its result (if any) or exception in case of failure.
 * <br><br>
 * The <code>FutureResult</code> has an intrinsic timeout set when the related message is sent, which puts a limit on the amount of time you can wait for message completion.
 * However, even if the future expires, the associated message will be always processed by its actor.
 *
 * @author Sergio Bossa
 */
public interface FutureResult {

    /**
     * Await for this future to complete. You can await at most the amount of time provided
     * by {@link #getTimeoutInNanos()}, which is computed from the time the related message is sent.<br>
     * After the elapsed timeout, the future will be considered as expired (see {@link #isExpired()}),
     * and additional calls to this method will return immediately.
     */
    public void await();

    /**
     * Check if the message computation associated with this future has been completed.<br>
     * Calling {@link await()} on a completed future has no effect and returns immediately.
     *
     * @return True if completed, false otherwise.
     */
    public boolean isCompleted();

    /**
     * Check if this future is expired.<br>
     * A future is considered to be expired when the associated timeout (see {@link #getTimeoutInNanos()}) has already elapsed.<br>
     * Calling {@link await()} on an expired future has no effect and returns immediately.
     *
     * @return True if expired, false otherwise.
     */
    public boolean isExpired();

    /**
     * Get the amount of time (in nanoseconds) after which this future will be considered as expired (see {@link #isExpired()}).<br>
     *
     * @return This future timeout in nanoseconds.
     */
    public long getTimeoutInNanos();

    /**
     * Get the result of the message computation, if any.
     *
     * @return The result of the message computation, or null if the computation had no result or if the future expired before
     * the computation actually completed.
     */
    public Object getResult();

    /**
     * This method returns a not null value only when the message computation completed by throwing an exception: in such a case.
     * an {@link com.googlecode.actorom.support.ActorExecutionException} is returned, containing the original exception as its cause.
     *
     * @return An {@link com.googlecode.actorom.support.ActorExecutionException} in case of message computation failure,
     * or null if the computation completed successfully or if the future expired before the computation actually completed.
     */
    public ActorExecutionException getException();
}
